package cn.jingyuan.bee.utils;

import cn.jingyuan.bee.utils.convert.Convert;

/**
 * Boolean 类型相关工具类
 */
public class BooleanUtils {

    /** 表示为真的字符串 */
    private static final String[] TRUE_ARRAY = {"true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真"};

    /**
     * 取相反值
     *
     * @param bool Boolean 值
     *
     * @return 相反的 Boolean 值
     */
    public static Boolean negate(Boolean bool) {
        if (bool == null) {
            return null;
        }
        return bool.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
    }

    /**
     * 检查 {@code Boolean} 值是否为 {@code true}
     *
     * <pre>
     *   BooleanUtils.isTrue(Boolean.TRUE)  = true
     *   BooleanUtils.isTrue(Boolean.FALSE) = false
     *   BooleanUtils.isTrue(null)          = false
     * </pre>
     *
     * @param bool 被检查的 Boolean 值
     *
     * @return 当值为 true 且非 null 时返回 {@code true}
     */
    public static boolean isTrue(Boolean bool) {
        return Boolean.TRUE.equals(bool);
    }

    /**
     * 检查 “bool” 字符串是否为 false
     * <pre>
     *     1、{"true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真"} 为真 ，其他为 false
     * </pre>
     *
     * @param bool
     *
     * @return
     */
    public static boolean isTrue(String bool) {
        return BooleanUtils.toBoolean(bool);
    }

    /**
     * 检查 {@code Boolean} 值是否为 {@code false}
     *
     * <pre>
     *   BooleanUtils.isFalse(Boolean.TRUE)  = false
     *   BooleanUtils.isFalse(Boolean.FALSE) = true
     *   BooleanUtils.isFalse(null)          = false
     * </pre>
     *
     * @param bool 被检查的 Boolean 值
     *
     * @return 当值为 false 且非 null 时返回 {@code true}
     */
    public static boolean isFalse(Boolean bool) {
        return Boolean.FALSE.equals(bool);
    }

    /**
     * 检查 “bool” 字符串是否为 false
     * <pre>
     *     1、{"true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真"} 为真 ，其他为 false
     * </pre>
     *
     * @param bool
     *
     * @return 当值为 false 且非 null 时返回 {@code true}
     */
    public static boolean isFalse(String bool) {
        return !BooleanUtils.toBoolean(bool);
    }

    /**
     * 取相反值
     *
     * @param bool Boolean 值
     *
     * @return 相反的 Boolean 值
     */
    public static boolean negate(boolean bool) {
        return !bool;
    }

    /**
     * 转换字符串为 boolean 值
     *
     * @param string 字符串
     *
     * @return boolean 值
     */
    public static boolean toBoolean(String string) {
        if (StringUtils.isNotBlank(string)) {
            string = string.trim().toLowerCase();
            return ArrayUtils.contains(TRUE_ARRAY, string);
        }
        return false;
    }

    /**
     * 转换数字为 boolean 值
     *
     * @param number 数字
     *
     * @return boolean 值
     */
    public static boolean toBoolean(Number number) {
        if (ObjectUtils.isNotNull(number)) {
            String string = number.toString();
            return ArrayUtils.contains(TRUE_ARRAY, string);
        }
        return false;
    }

    /**
     * boolean 值转为 int
     *
     * @param value Boolean 值
     *
     * @return int 值
     */
    public static int toInt(boolean value) {
        return value ? 1 : 0;
    }

    /**
     * boolean 值转为 Integer
     *
     * @param value Boolean 值
     *
     * @return Integer 值
     */
    public static Integer toInteger(boolean value) {
        return Integer.valueOf(toInt(value));
    }

    /**
     * boolean 值转为 char
     *
     * @param value Boolean 值
     *
     * @return char 值
     */
    public static char toChar(boolean value) {
        return (char) toInt(value);
    }

    /**
     * boolean 值转为 Character
     *
     * @param value Boolean 值
     *
     * @return Character 值
     */
    public static Character toCharacter(boolean value) {
        return Character.valueOf(toChar(value));
    }

    /**
     * boolean 值转为 byte
     *
     * @param value Boolean 值
     *
     * @return byte 值
     */
    public static byte toByte(boolean value) {
        return (byte) toInt(value);
    }

    /**
     * boolean 值转为 Byte
     *
     * @param value Boolean 值
     *
     * @return Byte 值
     */
    public static Byte toByteObj(boolean value) {
        return Byte.valueOf(toByte(value));
    }

    /**
     * boolean 值转为 long
     *
     * @param value Boolean 值
     *
     * @return long 值
     */
    public static long toLong(boolean value) {
        return toInt(value);
    }

    /**
     * boolean 值转为 Long
     *
     * @param value Boolean 值
     *
     * @return Long 值
     */
    public static Long toLongObj(boolean value) {
        return Long.valueOf(toLong(value));
    }

    /**
     * boolean 值转为 short
     *
     * @param value Boolean 值
     *
     * @return short 值
     */
    public static short toShort(boolean value) {
        return (short) toInt(value);
    }

    /**
     * boolean 值转为 Short
     *
     * @param value Boolean 值
     *
     * @return Short 值
     */
    public static Short toShortObj(boolean value) {
        return Short.valueOf(toShort(value));
    }

    /**
     * boolean 值转为 float
     *
     * @param value Boolean 值
     *
     * @return float 值
     */
    public static float toFloat(boolean value) {
        return (float) toInt(value);
    }

    /**
     * boolean 值转为 Float
     *
     * @param value Boolean 值
     *
     * @return float 值
     */
    public static Float toFloatObj(boolean value) {
        return Float.valueOf(toFloat(value));
    }

    /**
     * boolean 值转为 double
     *
     * @param value Boolean 值
     *
     * @return double 值
     */
    public static double toDouble(boolean value) {
        return toInt(value);
    }

    /**
     * boolean 值转为 double
     *
     * @param value Boolean 值
     *
     * @return double 值
     */
    public static Double toDoubleObj(boolean value) {
        return Double.valueOf(toDouble(value));
    }

    /**
     * 将 boolean 转换为字符串 {@code 'true'} 或者 {@code 'false'}.
     *
     * <pre>
     *   BooleanUtils.toStringTrueFalse(true)   = "true"
     *   BooleanUtils.toStringTrueFalse(false)  = "false"
     * </pre>
     *
     * @param bool Boolean 值
     *
     * @return {@code 'true'}, {@code 'false'}
     */
    public static String toStringTrueFalse(boolean bool) {
        return toString(bool, "true", "false");
    }

    /**
     * 将 boolean 转换为字符串 {@code 'on'} 或者 {@code 'off'}.
     *
     * <pre>
     *   BooleanUtils.toStringOnOff(true)   = "on"
     *   BooleanUtils.toStringOnOff(false)  = "off"
     * </pre>
     *
     * @param bool Boolean 值
     *
     * @return {@code 'on'}, {@code 'off'}
     */
    public static String toStringOnOff(boolean bool) {
        return toString(bool, "on", "off");
    }

    /**
     * 将 boolean 转换为字符串 {@code 'yes'} 或者 {@code 'no'}.
     *
     * <pre>
     *   BooleanUtils.toStringYesNo(true)   = "yes"
     *   BooleanUtils.toStringYesNo(false)  = "no"
     * </pre>
     *
     * @param bool Boolean 值
     *
     * @return {@code 'yes'}, {@code 'no'}
     */
    public static String toStringYesNo(boolean bool) {
        return toString(bool, "yes", "no");
    }

    /**
     * 将 boolean 转换为字符串
     *
     * <pre>
     *   BooleanUtils.toString(true, "true", "false")   = "true"
     *   BooleanUtils.toString(false, "true", "false")  = "false"
     * </pre>
     *
     * @param bool Boolean 值
     * @param trueString 当值为 {@code true} 时返回此字符串, 可能为 {@code null}
     * @param falseString 当值为 {@code false} 时返回此字符串, 可能为 {@code null}
     *
     * @return 结果值
     */
    public static String toString(boolean bool, String trueString, String falseString) {
        return bool ? trueString : falseString;
    }

    /**
     * 对 Boolean 数组取与
     *
     * <pre>
     *   BooleanUtils.and(true, true)         = true
     *   BooleanUtils.and(false, false)       = false
     *   BooleanUtils.and(true, false)        = false
     *   BooleanUtils.and(true, true, false)  = false
     *   BooleanUtils.and(true, true, true)   = true
     * </pre>
     *
     * @param array {@code Boolean} 数组
     *
     * @return 取与为真返回 {@code true}
     */
    public static boolean and(boolean... array) {
        if (ArrayUtils.isEmpty(array)) {
            throw new IllegalArgumentException("The Array must not be empty !");
        }
        for (final boolean element : array) {
            if (!element) {
                return false;
            }
        }
        return true;
    }

    /**
     * 对 Boolean 数组取与
     *
     * <pre>
     *   BooleanUtils.and(Boolean.TRUE, Boolean.TRUE)                 = Boolean.TRUE
     *   BooleanUtils.and(Boolean.FALSE, Boolean.FALSE)               = Boolean.FALSE
     *   BooleanUtils.and(Boolean.TRUE, Boolean.FALSE)                = Boolean.FALSE
     *   BooleanUtils.and(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE)   = Boolean.TRUE
     *   BooleanUtils.and(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE
     *   BooleanUtils.and(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE)  = Boolean.FALSE
     * </pre>
     *
     * @param array {@code Boolean} 数组
     *
     * @return 取与为真返回 {@code true}
     */
    public static Boolean and(final Boolean... array) {
        if (ArrayUtils.isEmpty(array)) {
            throw new IllegalArgumentException("The Array must not be empty !");
        }
        final boolean[] primitive = Convert.convert(boolean[].class, array);
        return Boolean.valueOf(and(primitive));
    }

    /**
     * 对 Boolean 数组取或
     *
     * <pre>
     *   BooleanUtils.or(true, true)          = true
     *   BooleanUtils.or(false, false)        = false
     *   BooleanUtils.or(true, false)         = true
     *   BooleanUtils.or(true, true, false)   = true
     *   BooleanUtils.or(true, true, true)    = true
     *   BooleanUtils.or(false, false, false) = false
     * </pre>
     *
     * @param array {@code Boolean} 数组
     *
     * @return 取或为真返回 {@code true}
     */
    public static boolean or(boolean... array) {
        if (ArrayUtils.isEmpty(array)) {
            throw new IllegalArgumentException("The Array must not be empty !");
        }
        for (final boolean element : array) {
            if (element) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对 Boolean 数组取或
     *
     * <pre>
     *   BooleanUtils.or(Boolean.TRUE, Boolean.TRUE)                  = Boolean.TRUE
     *   BooleanUtils.or(Boolean.FALSE, Boolean.FALSE)                = Boolean.FALSE
     *   BooleanUtils.or(Boolean.TRUE, Boolean.FALSE)                 = Boolean.TRUE
     *   BooleanUtils.or(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE)    = Boolean.TRUE
     *   BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE)  = Boolean.TRUE
     *   BooleanUtils.or(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE)   = Boolean.TRUE
     *   BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
     * </pre>
     *
     * @param array {@code Boolean} 数组
     *
     * @return 取或为真返回 {@code true}
     */
    public static Boolean or(Boolean... array) {
        if (ArrayUtils.isEmpty(array)) {
            throw new IllegalArgumentException("The Array must not be empty !");
        }
        final boolean[] primitive = Convert.convert(boolean[].class, array);
        return Boolean.valueOf(or(primitive));
    }

    /**
     * 对 Boolean 数组取异或
     *
     * <pre>
     *   BooleanUtils.xor(true, true)   = false
     *   BooleanUtils.xor(false, false) = false
     *   BooleanUtils.xor(true, false)  = true
     *   BooleanUtils.xor(true, true)   = false
     *   BooleanUtils.xor(false, false) = false
     *   BooleanUtils.xor(true, false)  = true
     * </pre>
     *
     * @param array {@code boolean} 数组
     *
     * @return 如果异或计算为 true 返回 {@code true}
     */
    public static boolean xor(boolean... array) {
        if (ArrayUtils.isEmpty(array)) {
            throw new IllegalArgumentException("The Array must not be empty");
        }

        boolean result = false;
        for (final boolean element : array) {
            result ^= element;
        }

        return result;
    }

    /**
     * 对 Boolean 数组取异或
     *
     * <pre>
     *   BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE })   = Boolean.FALSE
     *   BooleanUtils.xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE }) = Boolean.FALSE
     *   BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE })  = Boolean.TRUE
     * </pre>
     *
     * @param array {@code Boolean} 数组
     *
     * @return 异或为真取 {@code true}
     */
    public static Boolean xor(Boolean... array) {
        if (ArrayUtils.isEmpty(array)) {
            throw new IllegalArgumentException("The Array must not be empty !");
        }
        final boolean[] primitive = Convert.convert(boolean[].class, array);
        return Boolean.valueOf(xor(primitive));
    }

    /**
     * 给定类是否为 Boolean 或者 boolean
     *
     * @param clazz 类
     *
     * @return 是否为 Boolean 或者 boolean
     */
    public static boolean isBoolean(Class<?> clazz) {
        return (clazz == Boolean.class || clazz == boolean.class);
    }

}
